/* -*- mode: c++ -*-
**
** top.cpp
**
** top level instatiations and simulation control
** 
** Made by Kjetil Svarstad
** 
*/


#include <systemc.h>

#include "if.h"
#include "button.h"
#include "control.h"
#include "simple_bus.h"
#include "simple_bus_arbiter.h"
#include "simple_bus_fast_mem.h"
#include <iostream>



class top : public sc_module 
{
	public:
  Button * iButtons[10]; // 10 pointers
  Control * iControl;   // single pointer
  buttonAdapter * iAdapters[10];
  simple_bus                   * iBus;
  simple_bus_fast_mem          * iFastMem;
  simple_bus_arbiter	       * iArbiter;
  sc_clock                     * C1;
  int button_time;

  top (sc_module_name name) : sc_module (name) 
  {
    // Creating instances
    iBus = new simple_bus("bus");
    iFastMem = new simple_bus_fast_mem("FastMem", 0, 4095);
    iArbiter = new simple_bus_arbiter("arbiter");
    C1 = new sc_clock("BusClock", 10, SC_US);

    button_time = TIMEOUT;
    // Creating buttons and connecting to bus.
    // Need a char buffer to create unique instance names in:
    char buf[20];
    char buf2[20];
    for (int i = 0; i <= 9; i++) 
    {
      // Create unique name
      sprintf (buf, "Button%d\0", i);
      sprintf (buf2, "Adapter%d\0", i);
      // Create specific Button and Adapter instance
      iButtons[i] = new Button (buf, i);
      iAdapters[i] = new buttonAdapter(buf2, i);
      // and then connect it, the '*' dereferences the button pointer!
      iAdapters[i]->busp(*iBus);
			iAdapters[i]->buttonp(*(iButtons[i]));
      iButtons[i]->busp (*(iAdapters[i]));
    }
    
    // Create control and connect to the bus.
    iControl = new Control("Control");
    iControl->busp(*iBus);
    iBus->arbiter_port(*iArbiter);
    iBus->slave_port(*iFastMem);
    	iBus->clock(*C1);
    SC_HAS_PROCESS(top);
    SC_THREAD(main);
  }
  void main(void)
  {
		// Push correct sequence of buttons
		/*
		int correctSequence[9] = {3,8,1,2,9,5,7,6,4};
		for(int i=0;i<=8;i++)
		{
			wait(1,SC_NS);
			iButtons[correctSequence[i]]->PUSH.write(true);
			wait(1,SC_NS);
			iButtons[correctSequence[i]]->PUSH.write(false);
		}
		*/
		// Push incorrect sequence of buttons
		cout << "Top::main" << endl;
		int incorrectSequence[11] = {1,2,3,4,5,3,4,6,3,4,9};
		int correctSequence[9] = {3,8,1,2,9,5,7,6,4};
		for(int i=0;i<=9;i++)
		{
		  //cout <<"Ahead of wait 500 ms" << endl;
		        wait(5*button_time,SC_MS);
			//cout << "After wait" << endl;
			iButtons[correctSequence[i]]->PUSH.write(true);
			wait(button_time,SC_MS);
			iButtons[correctSequence[i]]->PUSH.write(false);
				
		}
		sc_stop();
  }
};


int sc_main (int argc , char *argv[])  {
 // instantiate top
	top iTop("Top");
  // tracing of signals
  char temp[20];
  sc_trace_file* tracefile;
  tracefile = sc_create_vcd_trace_file("oving2trace");
  for(int i = 0; i<=9;i++)
  {
		sprintf(temp, "Button%i_push\0",i);
		sc_trace(tracefile,iTop.iButtons[i]->PUSH,temp);
		sprintf(temp, "Button%i_light\0",i);
		sc_trace(tracefile,iTop.iButtons[i]->light,temp);
	}
   srand ( time(NULL) );
  sc_start (); 
  return 0;
}



